using System;
using System.Collections.Generic;
using System.Diagnostics;
using TAAlert.CommonUtils;

namespace TAAlert.BackTest
{
    /// <summary>Trend follwoing strategy: Long if price is above Exponential moving average and Short if price is below EMA</summary>
    class EMAStrategy : Strategy
    {
        static private readonly TraceSwitch traceM = new TraceSwitch("EMAStrategy", "Debug info for Strategy class");
        private List<double> emaM;      // exp moving average. The same size as prices

        /// <summary>Simple Exponential moving average strategy. LONG if price is above EMA, SHORT if price is below EMA</summary>
        /// <param name="nEMA">Exponential moving average period length</param>
        /// <param name="startDate">Start date of the investment strategy</param>
        /// <param name="endDate">End date of the investment strategy</param>
        /// <param name="prices">Dated list of closing prices for the underlying. It should start well before startDate</param>
        public EMAStrategy(int nEMA, DateTime startDate, DateTime endDate, SortedList<DateTime, double> prices)
            : base(startDate, endDate, prices, traceM)
        {
            Debug.WriteLineIf(traceM.TraceInfo, "--> Entering EMAStrategy(" + nEMA + ", " + startDate.ToShortDateString() + ", " + endDate.ToShortDateString() + ", prices)");
            // calculate EMA
            this.emaM = EMAEvaluator.calcEMAArray(this.Prices.Values, nEMA);
        }

        /// <summary>Generate list of investment positions. (+1 long, -1 short, 0 neutral)</summary>
        /// <returns>List of dated positions. The positions are established on date close and affect only the next day perofmrance.</returns>
        override public SortedList<DateTime, int> generate()
        {
            Debug.WriteLineIf(traceM.TraceInfo, "--> Entering EMAStrategy.generate()");
            Debug.Indent();
            int n = this.EndIx - this.StartIx + 1;

            SortedList<DateTime, int> pos = new SortedList<DateTime, int>(n);
            Debug.WriteLineIf(traceM.TraceVerbose, "Date,Price,EMA,Position");
            for (int ix = this.StartIx; ix <= this.EndIx; ++ix)
            {
                DateTime date = this.Prices.Keys[ix];
                int signal = (int) EMAEvaluator.emaSignal(this.Prices.Values[ix], emaM[ix]);
                pos.Add(date, signal);
                Debug.WriteLineIf(traceM.TraceVerbose, date.ToShortDateString() + ", " + this.Prices.Values[ix].ToString(".##") + ", " + emaM[ix].ToString(".##") + ", " + signal);
            }
            Debug.WriteLineIf(traceM.TraceInfo, "... generated " + pos.Count + " signals");
            Debug.Unindent();
            return pos;
        }

    }
}
